package cn.lblbc.webbrowser.views

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Matrix
import android.graphics.PointF
import android.util.AttributeSet
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import androidx.appcompat.widget.AppCompatImageView
import kotlin.math.max
import kotlin.math.min

class ZoomableImageView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr) {

    private var matrix = Matrix()
    private var savedMatrix = Matrix()
    private var start = PointF()
    private var mid = PointF()
    private var oldDist = 1f
    private var minScale = 1f
    private var maxScale = 4f
    private var currentScale = 1f
    private var mode = NONE

    private lateinit var scaleDetector: ScaleGestureDetector
    private lateinit var gestureDetector: GestureDetector

    companion object {
        private const val NONE = 0
        private const val DRAG = 1
        private const val ZOOM = 2
    }

    init {
        scaleType = ScaleType.MATRIX
        scaleDetector = ScaleGestureDetector(context, ScaleListener())
        gestureDetector = GestureDetector(context, GestureListener())
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        scaleDetector.onTouchEvent(event)
        gestureDetector.onTouchEvent(event)

        when (event.action and MotionEvent.ACTION_MASK) {
            MotionEvent.ACTION_DOWN -> {
                savedMatrix.set(matrix)
                start.set(event.x, event.y)
                mode = DRAG
                parent?.requestDisallowInterceptTouchEvent(currentScale > minScale)
            }

            MotionEvent.ACTION_POINTER_DOWN -> {
                oldDist = spacing(event)
                if (oldDist > 10f) {
                    savedMatrix.set(matrix)
                    midPoint(mid, event)
                    mode = ZOOM
                    parent?.requestDisallowInterceptTouchEvent(true)
                }
            }

            MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> {
                mode = NONE
                parent?.requestDisallowInterceptTouchEvent(false)
            }

            MotionEvent.ACTION_MOVE -> {
                when (mode) {
                    DRAG -> {
                        if (currentScale > minScale) {
                            matrix.set(savedMatrix)
                            val dx = event.x - start.x
                            val dy = event.y - start.y
                            matrix.postTranslate(dx, dy)
                            parent?.requestDisallowInterceptTouchEvent(true)
                        } else {
                            parent?.requestDisallowInterceptTouchEvent(false)
                        }
                    }
                    ZOOM -> {
                        val newDist = spacing(event)
                        if (newDist > 10f) {
                            matrix.set(savedMatrix)
                            val scale = newDist / oldDist
                            matrix.postScale(scale, scale, mid.x, mid.y)
                            parent?.requestDisallowInterceptTouchEvent(true)
                        }
                    }
                }
            }
        }

        // 应用变换并检查边界
        checkAndApplyMatrix()
        return true
    }

    private inner class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener() {
        override fun onScale(detector: ScaleGestureDetector): Boolean {
            val scaleFactor = detector.scaleFactor
            matrix.postScale(scaleFactor, scaleFactor, detector.focusX, detector.focusY)
            parent?.requestDisallowInterceptTouchEvent(true)
            return true
        }
    }

    private inner class GestureListener : GestureDetector.SimpleOnGestureListener() {
        override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
            // 单击还原到初始状态
            animateToScale(minScale, e.x, e.y)
            return true
        }

        override fun onDoubleTap(e: MotionEvent): Boolean {
            // 双击放大
            val targetScale = when {
                currentScale <= minScale -> minScale * 2f
                currentScale < maxScale -> maxScale
                else -> minScale
            }
            animateToScale(targetScale, e.x, e.y)
            return true
        }
    }

    private fun checkAndApplyMatrix() {
        val values = FloatArray(9)
        matrix.getValues(values)
        
        val scaleX = values[Matrix.MSCALE_X]
        val scaleY = values[Matrix.MSCALE_Y]
        currentScale = scaleX
        
        // 限制缩放范围
        if (scaleX < minScale || scaleX > maxScale) {
            val scale = max(minScale, min(maxScale, scaleX))
            matrix.setScale(scale, scale)
            currentScale = scale
        }
        
        // 检查边界
        checkBounds()
        
        // 应用变换
        imageMatrix = matrix
    }

    private fun checkBounds() {
        val values = FloatArray(9)
        matrix.getValues(values)
        
        val transX = values[Matrix.MTRANS_X]
        val transY = values[Matrix.MTRANS_Y]
        val scaleX = values[Matrix.MSCALE_X]
        
        val viewWidth = width.toFloat()
        val viewHeight = height.toFloat()
        
        if (drawable != null) {
            val drawableWidth = drawable.intrinsicWidth * scaleX
            val drawableHeight = drawable.intrinsicHeight * scaleX
            
            var deltaX = 0f
            var deltaY = 0f
            
            // 检查水平边界
            if (drawableWidth <= viewWidth) {
                deltaX = (viewWidth - drawableWidth) / 2 - transX
            } else {
                if (transX > 0) {
                    deltaX = -transX
                } else if (transX < viewWidth - drawableWidth) {
                    deltaX = viewWidth - drawableWidth - transX
                }
            }
            
            // 检查垂直边界
            if (drawableHeight <= viewHeight) {
                deltaY = (viewHeight - drawableHeight) / 2 - transY
            } else {
                if (transY > 0) {
                    deltaY = -transY
                } else if (transY < viewHeight - drawableHeight) {
                    deltaY = viewHeight - drawableHeight - transY
                }
            }
            
            matrix.postTranslate(deltaX, deltaY)
        }
    }

    private fun spacing(event: MotionEvent): Float {
        if (event.pointerCount < 2) return 0f
        val x = event.getX(0) - event.getX(1)
        val y = event.getY(0) - event.getY(1)
        return kotlin.math.sqrt((x * x + y * y).toDouble()).toFloat()
    }

    private fun midPoint(point: PointF, event: MotionEvent) {
        if (event.pointerCount < 2) return
        val x = event.getX(0) + event.getX(1)
        val y = event.getY(0) + event.getY(1)
        point.set(x / 2, y / 2)
    }

    fun resetZoom() {
        if (drawable == null) {
            matrix.reset()
            currentScale = 1f
            imageMatrix = matrix
            return
        }
        
        val drawableWidth = drawable.intrinsicWidth.toFloat()
        val drawableHeight = drawable.intrinsicHeight.toFloat()
        val viewWidth = width.toFloat()
        val viewHeight = height.toFloat()
        
        if (viewWidth == 0f || viewHeight == 0f) {
            matrix.reset()
            currentScale = 1f
            imageMatrix = matrix
            return
        }
        
        // 计算适合屏幕的缩放比例
        val scaleX = viewWidth / drawableWidth
        val scaleY = viewHeight / drawableHeight
        val scale = minOf(scaleX, scaleY)
        
        // 计算居中位置
        val scaledWidth = drawableWidth * scale
        val scaledHeight = drawableHeight * scale
        val dx = (viewWidth - scaledWidth) / 2
        val dy = (viewHeight - scaledHeight) / 2
        
        // 重置矩阵并设置居中
        matrix.reset()
        matrix.postScale(scale, scale)
        matrix.postTranslate(dx, dy)
        
        currentScale = scale
        minScale = scale
        imageMatrix = matrix
    }

    override fun setImageDrawable(drawable: android.graphics.drawable.Drawable?) {
        super.setImageDrawable(drawable)
        post { 
            resetZoom()
            centerImage()
        }
    }

    override fun setImageResource(resId: Int) {
        super.setImageResource(resId)
        post { 
            resetZoom()
            centerImage()
        }
    }
    
    private fun centerImage() {
        if (drawable == null) return
        
        val drawableWidth = drawable.intrinsicWidth.toFloat()
        val drawableHeight = drawable.intrinsicHeight.toFloat()
        val viewWidth = width.toFloat()
        val viewHeight = height.toFloat()
        
        if (viewWidth == 0f || viewHeight == 0f) return
        
        // 计算缩放比例，确保图片完全显示
        val scaleX = viewWidth / drawableWidth
        val scaleY = viewHeight / drawableHeight
        val scale = minOf(scaleX, scaleY)
        
        // 计算居中位置
        val scaledWidth = drawableWidth * scale
        val scaledHeight = drawableHeight * scale
        val dx = (viewWidth - scaledWidth) / 2
        val dy = (viewHeight - scaledHeight) / 2
        
        // 设置变换矩阵
        matrix.reset()
        matrix.postScale(scale, scale)
        matrix.postTranslate(dx, dy)
        
        currentScale = scale
        minScale = scale // 设置最小缩放为适合屏幕的缩放
        imageMatrix = matrix
    }
    
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        if (drawable != null) {
            post { centerImage() }
        }
    }

    private fun animateToScale(targetScale: Float, focusX: Float, focusY: Float) {
        val startScale = currentScale
        val scaleChange = targetScale - startScale
        
        if (kotlin.math.abs(scaleChange) < 0.01f) return
        
        val startMatrix = Matrix(matrix)
        val startValues = FloatArray(9)
        startMatrix.getValues(startValues)
        
        // 计算目标矩阵
        val targetMatrix = Matrix(startMatrix)
        val scaleFactor = targetScale / startScale
        targetMatrix.postScale(scaleFactor, scaleFactor, focusX, focusY)
        
        val targetValues = FloatArray(9)
        targetMatrix.getValues(targetValues)
        
        // 动画实现
        val animator = ValueAnimator.ofFloat(0f, 1f)
        animator.duration = 300
        animator.addUpdateListener { animation ->
            val progress = animation.animatedValue as Float
            
            // 插值计算当前矩阵值
            val currentValues = FloatArray(9)
            for (i in 0..8) {
                currentValues[i] = startValues[i] + (targetValues[i] - startValues[i]) * progress
            }
            
            matrix.setValues(currentValues)
            currentScale = startScale + scaleChange * progress
            
            // 检查边界并应用
            checkBounds()
            imageMatrix = matrix
        }
        animator.start()
    }
}